Last updated: Jul 1st, 1:53pm
If you have an Express Checkout integration, PayPal recommends upgrading to PayPal Checkout using the JavaScript SDK. The JavaScript SDK has the following benefits:
If your current integration is Express Checkout, you must upgrade to PayPal Checkout. You can use your site’s branding with PayPal Checkout, allowing customers to pay with PayPal, Pay Later options, Venmo, and alternative payment methods.
Locate the endpoint URLs in your code that manage starting, reviewing, and completing paymetns. Check the API requests for the following METHOD parameter values:
SetExpressCheckout, GetExpressCheckoutDetails, DoExpressCheckoutPayment
Review the core API calls from your current integration and make a list of the parameters, such as PAYMENTREQUEST_0_AMT.
Map these parameters to the new API using our parameter mapping tool in our PayPal API Transformer.
If you don't already have one, sign up for a PayPal developer account.
Follow this onboarding document to get a client ID and secret, access token, and your sandbox account credentials.
Follow this account configuration document to set up your sandbox account and test purchases before going live in your live account.
Set up your front end to use PayPal payment buttons in PayPal Checkout. Select your upgrade path: choose 'For NVP/SOAP API-only integration' if you currently have an API-only integration, or choose 'For NVP/SOAP API and JavaScript SDK v4' if you're currently using checkout.js.
PayPal's JavaScript SDK supports how you want to accept payments on your website. Our SDK handles displaying the buttons for PayPal and other payment methods, so your customers can pay with whatever method they choose. See Getting started for more information.
1. Follow steps 1-5 in the Integrate PayPal Checkout guide to set up and customize your PayPal payment buttons with JavaScript SDK v5.
1<!DOCTYPE html>2<html>3 <head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>PayPal JS SDK PayPal Checkout Integration</title>7 </head>8 <body>9 <div id="paypal-button-container"></div>10 <p id="result-message"></p>111213 <!-- Initialize the JS-SDK -->14 <script15 src="https://www.paypal.com/sdk/js?client-id=test&buyer-country=US¤cy=USD&components=buttons&enable-funding=venmo,paylater,card"16 data-sdk-integration-source="developer-studio"17 ></script>18 <script src="app.js"></script>1920 </body>21</html>22
If you are using a previous version of PayPal's JavascriptSDK (checkout.js), upgrade your SDK to access the full rnage of features offered by PayPal Checkout.
1. Follow this guide to upgrade your SDK to the most recent version.
1<!DOCTYPE html>2<html lang="en">3<head>4 <meta charset="UTF-8">5 <title>PayPal Express Checkout (legacy checkout.js)</title>6 <script src="https://www.paypalobjects.com/api/checkout.js"></script>7</head>8<body>9 <div id="paypal-button-container"></div>1011 <script>12 paypal.Button.render({13 env: 'sandbox', // or 'production'1415 client: {16 sandbox: 'YOUR_SANDBOX_CLIENT_ID',17 production: 'YOUR_PRODUCTION_CLIENT_ID'18 },1920 commit: true, // Show "Pay Now"2122 payment: function(data, actions) {23 // Create payment on client side (or call your server)24 return actions.payment.create({25 payment: {26 transactions: [{27 amount: { total: '10.00', currency: 'USD' },28 description: 'Order #12345 - Test payment'29 }],30 note_to_payer: 'Contact us for any questions.'31 }32 });33 },3435 onAuthorize: function(data, actions) {36 // Execute payment after customer approves37 return actions.payment.execute().then(function(paymentDetails) {38 console.log('Payment completed!', paymentDetails);39 alert('Payment complete! Transaction ID: ' + paymentDetails.id);40 // Typically, you'd send paymentDetails.id to your server here41 });42 },4344 onCancel: function(data) {45 console.log('Payment cancelled', data);46 alert('Payment cancelled.');47 },4849 onError: function(err) {50 console.error('Error during checkout', err);51 alert('An error occurred: ' + err);52 }53 }, '#paypal-button-container');54 </script>55</body>56</html>57
1<!DOCTYPE html>2<html>3 <head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>PayPal JS SDK PayPal Checkout Integration</title>7 </head>8 <body>9 <div id="paypal-button-container"></div>10 <p id="result-message"></p>111213 <!-- Initialize the JS-SDK -->14 <script15 src="https://www.paypal.com/sdk/js?client-id=test&buyer-country=US¤cy=USD&components=buttons&enable-funding=venmo,paylater,card"16 data-sdk-integration-source="developer-studio"17 ></script>18 <script src="app.js"></script>1920 </body>21</html>22
If you have an Express Checkout integration, you must set up server-side processing. You'll need to generate an access token, upgrade your NVP/SOAP API integraiton to the Orders v2 API, and set up a listener to handle API responses.
The NVP/SOAP API handles authentication using API credentials, such as, USER, PWD and SIGNATURE. These credentials are passed directly in the request.
In contrast, the Orders v2 REST API uses OAuth 2.0 for authentication, which requires an access token. To generate an access token:
This example shows a generateAccessToken() function:
1<script>2 const PAYPAL_CLIENT_ID = 'YOUR_CLIENT_ID';3 const PAYPAL_CLIENT_SECRET = 'YOUR_CLIENT_SECRET';4 const BASE_URL = 'https://api-m.sandbox.paypal.com';56 async function generateAccessToken() {7 const auth = btoa(`${PAYPAL_CLIENT_ID}:${PAYPAL_CLIENT_SECRET}`);8 const response = await fetch(`${BASE_URL}/v1/oauth2/token`, {9 method: 'POST',10 headers: {11 'Authorization': `Basic ${auth}`,12 'Content-Type': 'application/x-www-form-urlencoded'13 },14 body: 'grant_type=client_credentials'15 });1617 const data = await response.json();18 if (!response.ok) {19 const msg = data.error_description || JSON.stringify(data);20 throw new Error(`Token request failed: ${msg}`);21 }22 return data.access_token;23 }2425 async function onGetTokenClick() {26 try {27 const token = await generateAccessToken();28 document.getElementById('result').textContent =29 `Access Token:\n${token}`;30 } catch (err) {31 document.getElementById('result').textContent =32 `Error generating token:\n${err.message}`;33 }34 }3536 document.getElementById('get-token')37 .addEventListener('click', onGetTokenClick);38</script>
Use the Orders v2 API to create, update, retrieve, authorize, and capture orders. Use the Payments v2 API for post-payment actions. The following table shows how a one-time payment request in NVP/SOAP API maps to a PayPal Checkout request in the Orders v2 REST API:
NVP/SOAP API | Orders v2 REST API |
METHOD=SetExpressCheckout | POST /v2/checkout/orders |
METHOD=GetExpressCheckoutDetails | GET /v2/checkout/orders/{order_id} |
METHOD=DoExpressCheckoutPayment | POST /v2/checkout/orders/{order_id}/capture |
To help you construct the request body to support the Orders v2 format, copy and paste your NVP/SOAP reqeuset body into our API Transformer tool.
THe NVP/SOAP integration uses the DoExpressCheckoutAPI to process both order updates and capture order requests. When you need to change the order details, such as the address or amount, after your original SetExpressCheckout call, you can make a single DoExpressCheckout call to simultaneously change the order details and capture the payment.
To change the order details between request and capture using PayPal Checkout, you need to make 2 calls to the Orders v2 API: an Update order PATCH request to update the order, and a Capture payment for order request to finalize the checkout flow.
The following are examples of NVP/SOAP API request payloads and how they map to and PayPal Checkout request in the Orders v2 REST API:
1paymentrequest_0_invnum=20256191010512&method=SetExpressCheckout3&signature=PII4&maxamt=2.005&version=2046&returnurl=http://mywesbite.com/return7&pwd=PII8&cancelurl=http://mywebsite.com/cancel9&user=PII10&paymenttype=Any
1curl -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2-H 'Content-Type: application/json' \3-H 'Authorization: Bearer {AUTHORIZATION TOKEN}' \4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "invoice_id": "2025619101051"9 }10 ],11 "payment_source": {12 "paypal": {13 "experience_context": {14 "return_url": "https://mywebsite.com/return",15 "cancel_url": "https://mywebsite.com/cancel"16 }17 }18 },19 "final_capture": false20}'
1method=GetExpressCheckoutDetails2&signature=xxxxxxxxx3&pwd=xxxxxx4&version=2045&user=xxxxxxx6&token=EC-9HU1611060099414978910
1curl https://api-m.sandbox.paypal.com/v2/checkout/orders/{id} \2-H 'Content-Type: application/json' \3-H 'Authorization: Bearer {AUTHORIZATION TOKEN}'45678910
1USER=xxxxxxxx2&PWD=xxxxxxxx3&SIGNATURE=xxxxx4&METHOD=DoExpressCheckoutPayments5&VERSION=124.06&TOKEN=EC-72D0681527109671C7&PAYMENTREQUEST_0_PAYMENTACTION=Sale8&PAYMENTREQUEST_0_AMT=111.11910
1curl -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders/2HX49812L18884342/capture' \2-H 'Content-Type: application/json' \3-H 'Prefer: return=representation' \4-H 'Authorization: Bearer bearer_access_token'5678910
Create a handleResponse function to set up a listener that returns an HTTP status code from the API response.
For more information about Orders V2 error scenarios, see OrdersV2 Error Messages page.
This example shows a handleResponse() function:
1async function handleResponse(response){2 try {3 const jsonResponse = await resonse.json();4 return {5 jsonResponse,6 httpStatusCode: response.status,7 };8 } catch (err) {9 const errorMessage = await response.text();10 throw new Error(errorMessage);11 }12}
Replace IPN(Instant Payment Notification) to webhooks for asynchronous event processing.
See the Orders v2 API reference to configure the details of your integration.
Before going live, test your integration in the sandbox environment. Learn more about card testing, simulating successful payments using test card numbers and generating card error scenarios using rejection triggers.
Follow this checklist to take your application live:
See Move your app to production for more details